﻿#pragma once

#include "common/define/types.h"

namespace os
{
    /// 路径分隔符
    static const char s_folder_sep = '/';

    /**
     * @brief 文件是否存在
     */
    bool path_exists(const file_path_t &file_path) noexcept;

    /**
     * @brief 文件大小
     */
    std::size_t file_size(std::FILE *file);

    /**
     * @brief 文件路径名
     */
    filename_t dir_name(const file_path_t &file_path) noexcept;

    /**
     * @brief 创建目录
     */
    bool create_dir(const file_path_t &file_path) noexcept;

    /**
     * @brief 打开文件
     * 文件访问模式字符串	含义	解释	若文件已存在的行动	若文件不存在的行动
     * "r"	读	为读取打开文件	从起始读取	打开失败
     * "w"	写	为写入创建文件	销毁内容	创建新文件
     * "a"	追加	追加到文件	写入到末尾	创建新文件
     * "r+"	扩展读	为读取/写入打开文件	从起始读取	错误
     * "w+"	扩展写	为读取/写入创建文件	销毁内容	创建新文件
     * "a+"	扩展追加	为读取/写入打开文件	写入到末尾	创建新文件
     * 文件访问模式标志 "b" 能可选地指定，以用二进制模式打开文件。此标志在 POSIX 系统上无效果，但例如在 Windows 上，它禁用 '\n' 和 '\x1A' 的特殊处理。
     * 在追加文件访问模式上，写入数据到文件尾，忽略文件位置指示器的当前位置。
     * 文件访问模式标志 "x" 能可选地追加到 "w" 或 "w+" 指定符。此标志强制函数在文件存在的情况下失败，而非重写文件。(C++17)
     * 若模式不是以上字符串之一，则行为未定义。一些实现定义额外的支持模式
     * @param fp 指向控制打开的文件流的对象的指针
     * @param filename 要关联文件流到的文件名
     * @param mode 确定文件访问模式的空终止字符串
     */
    bool fopen(std::FILE* &fp, const filename_t &filename, const std::string &mode);

    /**
     * @brief 关闭文件
     * 关闭给定的文件流。冲入任何未写入的缓冲数据到 OS 。舍弃任何未读取的缓冲数据。
     * @param fp 指向输出流的指针
     */
    void fclose(std::FILE* fp);
    
    /**
     * @brief 写入文件
     * 写 count 个来自给定数组 buffer 的对象到输出流fp。
     * @param fp 指向输出流的指针
     * @param buffer 指向数组中要被写入的首个对象的指针
     * @param count 要被写入的对象数
     */
    void fwrite(std::FILE* fp, const char* buffer, std::size_t count);

    /**
     * @brief 输出缓冲区写入文件
     * 对于输出流（和最近操作为输出的更新流），将来自 stream 缓冲区的未写入数据写入关联的输出设备。
     * 对于输入流（和最近操作为输入的更新流），行为未定义。
     * 若 stream 为空指针，则冲入所有打开的输出流，包含在库包内操作，或其他情况下程序不能直接访问的流。
     */
    void fflush(std::FILE* fp);
} // namespace os

#include "file_inl.h"